﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ESN.Models;
using System.Web.Script.Serialization;
using System.Web.Security;
using ESN.Helpers;
using ESN.Languages;
using System.Text.RegularExpressions;

namespace ESN.Controllers
{
    public class QuizController : Controller
    {
        //
        // GET: /Quiz/
        private ESNQuizDbContext db = new ESNQuizDbContext();
        private ESNCoreDbContext core = new ESNCoreDbContext();

        public ActionResult Index()
        {
            return View();
        }
        [Authorize]
        public ActionResult Create()
        {
            return View();
        }
        [Authorize]
        public ActionResult My()
        {
            var id = (Guid)Membership.GetUser().ProviderUserKey;
            var myEx = db.Exercises.Where(e => e.UserId == id);
            return View(myEx);
        }
        [Authorize]
        public ActionResult Edit(int id)
        {
            var ex = db.Exercises.Find(id);
            if (ex == null)
            {
                ViewBag.Detail = LangString.Load("not_exist", "Error");
                return View("Error");
            }
            ViewBag.Ques = Regex.Escape(ex.ExContent);
            ViewBag.Corr = Regex.Escape(ex.ExCorrect);
            ViewBag.Editting = true;
            return View(ex);
        }
        public ActionResult TestInfo(int? id)
        {
            if (!id.HasValue)
                return RedirectToAction("Index");

            var data = db.Exercises.Find(id);

            return View(data);
        }

        public ActionResult Test(int id)
        {
            if (id < 0)
                return RedirectToAction("Index");

            var ex = db.Exercises.Find(id);
            if(ex == null)
                return RedirectToAction("Index");
            int justDone = 0;
            if (Request.Cookies["userpref"] != null)
            {
                if (Request.Cookies["userpref"]["Exercise" + id.ToString()] != null)
                {
                    justDone = Convert.ToInt32(Request.Cookies["userpref"]["Exercise" + id.ToString()]);
                }
            }
            if (ex.ExShot.HasValue && justDone >= ex.ExShot)
            {
                if (!ex.ExFreeShot)
                {
                    ViewBag.Detail = "You are now metting the limit shot for this exercise (" + ex.ExShot.ToString() + ").";
                    return View("Error");
                }
                else
                {
                    ViewBag.IsFree = true;
                }
            }

            CookiesHelper.UpdateSubkey("userpref", "Exercise" + id.ToString(), (justDone + 1).ToString());
            ViewBag.ExId = id;

            return View();
        }

        [HttpPost]
        public string GetResult(AnsList ansList)
        {
            var parser = new JavaScriptSerializer();

            var ex = db.Exercises.Find(ansList.ExId);

            UserResult re = new UserResult();
            re.TimeSpend = ansList.TimeSpend;

            List<List<string>> correctList = parser.Deserialize<List<List<string>>>(ex.ExCorrect);

            List<Question> quesList = parser.Deserialize<List<Question>>(ex.ExContent);

            if (ex == null)
            {
                re.RePoint1 = 0;
                return parser.Serialize(re);
            }

            if(correctList.Count != ansList.Ans.Count)
                throw new HttpException(400, "Bad Request");
            //return ansList.Ans.Count.ToString() + " " + correctList.Count.ToString() + " " + quesList.Count.ToString();

            float point = 0;
            float total = 0;
            bool waiting = false;

            for (int i = 0; i < quesList.Count; i++)
            {
                total = total + quesList[i].point;
                if (ansList.Ans[i].Count == 0)
                    continue;

                int c = correctList.Count;

                switch (quesList[i].type)
                {
                    //mot dap an
                    case 0:
                        if (correctList[i][0] == ansList.Ans[i][0])
                            point = point + quesList[i].point;
                        break;
                    //1: nhieu dap an; 2: noi cot; 3: dien khuyet;
                    case 1:
                        if (ansList.Ans[i].Count - correctList[i].Count > 0)
                        {
                            c = c - (ansList.Ans[i].Count - correctList[i].Count);
                        }
                        for (int j = 0; j < correctList[i].Count; j++)
                        {
                            for (int t = 0; t < ansList.Ans[i].Count; t++)
                            {
                                if (correctList[i][j] == ansList.Ans[i][t])
                                    c++;
                            }
                        }
                        if (c < 0)
                            c = 0;
                        point = point + (c / correctList.Count) * quesList[i].point;
                        break;
                    case 2:
                    case 3:
                        for (int j = 0; j < correctList[i].Count; j++)
                        {
                            if (correctList[i][j] != ansList.Ans[i][j])
                                c--;
                        }
                        point = point + (c / correctList.Count) * quesList[i].point;
                        break;
                    //tra loi tu do
                    case 4:
                        waiting = true;
                        break;

                }
            }
            
            re.ExId = ansList.ExId;
            re.RePoint1 = point;
            re.ReContent = parser.Serialize(ansList.Ans);
            re.ReWatting = waiting;
            re.ReCreateTime = DateTime.Now;
            //if (User.Identity.IsAuthenticated)
            //    re.UserId = (Guid)Membership.GetUser().ProviderUserKey;
            //else if (Membership.ValidateUser(Request.QueryString["username"], Request.QueryString["password"]))
            //    re.UserId = (Guid)Membership.GetUser(Request.QueryString["username"]).ProviderUserKey;
            if (PermissionHelper.IsAuthenticated())
            {
                re.UserId = (Guid)Membership.GetUser().ProviderUserKey;
            }
            else
                return "{\"Point\" : " + re.RePoint1 + ", \"Ans\" : \"" + re.ReContent.Replace("\"", "\\\"") + "\", \"Total\": " + total + "}";

            if (!ex.ExDone.HasValue)
                ex.ExDone = 0;

            ESNCoreDbContext core = new ESNCoreDbContext();
            var UserOnline = core.Profiles.Find(re.UserId);

            if (ex.ExTrace || waiting)
            {
                db.UserResults.Add(re);
                db.SaveChanges();
                var about = "exercise|done|" + ex.ExId.ToString();
                var notices = core.UserNotices.OrderByDescending(n => n.NId).Where(n => n.NAbout == about);
                if (notices.Count() > 0)
                {
                    var notice = notices.First();
                    notice.NContent = "<a href=\"/Quiz/ViewResult?QId=" + re.ExId + "&RId="+ re.ReId +"\">" + UserOnline.DisplayName + "</a>, " + notice.NContent;
                    notice.NNew = true;
                    core.SaveChanges();
                }
                else
                {
                    UserNotice notice = new UserNotice();
                    notice.NContent = "<a href=\"/Quiz/ViewResult?QId=" + re.ExId + "&RId=" + re.ReId + "\">" + UserOnline.DisplayName + "</a> " + String.Format(LangString.Load("just_finish", "Quiz"), re.ExId);
                    notice.NAbout = about;
                    notice.NNew = true;
                    notice.UserId = ex.UserId;
                    core.UserNotices.Add(notice);
                    core.SaveChanges();
                }
            }
            else
            {
                //we will update for the....
                if (ex.ExAveragePoint.HasValue)
                    ex.ExAveragePoint = (int)((ex.ExAveragePoint * ex.ExDone + re.RePoint1) / (ex.ExDone + 1));
                else
                    ex.ExAveragePoint = (int)re.RePoint1;
            }

            if (ex.ExAverageTime.HasValue)
                ex.ExAverageTime = (int)((ex.ExAverageTime * ex.ExDone + ansList.TimeSpend) / (ex.ExDone + 1));
            else
                ex.ExAverageTime = ansList.TimeSpend;

            ex.ExDone++;

            return "{\"Point\" : \"" + re.RePoint1 + "\", \"Ans\" : \"" + re.ReContent.Replace("\"", "\\\"") + "\", \"ReId\" : " + re.ReId + ", \"Total\": " + total + "}";
        }

        public ActionResult ViewResult(int QId, int RId)
        {
            var e = db.Exercises.Find(QId);
            var r = db.UserResults.Find(RId);
            if (e == null || r == null)
            {
                ViewBag.Detail = LangString.Load("not_exist", "Error");
                return View("Error");
            }
            var u = core.Profiles.Find(r.UserId);

            var parser = new JavaScriptSerializer();
            List<Question> q = parser.Deserialize<List<Question>>(e.ExContent);
            List<List<string>> a = parser.Deserialize<List<List<string>>>(r.ReContent);
            List<List<string>> c = parser.Deserialize<List<List<string>>>(e.ExCorrect);
            Results s = new Results();
            s.questions = q;
            s.answers = a;
            s.corrects = c;

            ViewBag.At = r.ReCreateTime;
            ViewBag.Take = r.TimeSpend;
            ViewBag.UserName = u.UserName;
            ViewBag.DisplayName = u.DisplayName;
            ViewBag.Point = r.RePoint1;
            
            ViewBag.Ans = ESN.Languages.LangString.Load("answer", "Quiz");
            ViewBag.Corr = ESN.Languages.LangString.Load("correct", "Quiz");
            ViewBag.PointLabel = @ESN.Languages.LangString.Load("point", "Quiz");
            return View(s);
        }
    }
}
